/*************************************************************************
	> File Name: env.c
	> Author: 
	> Mail: 
	> Created Time: Sat 02 Nov 2019 06:07:41 PM PDT
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "shell.h"
#include "env.h"

#define DATA_LENGTH 50

extern char **environ;
static int search_ch(char ch, char *argvlist[]);
static int exec_set_cmd(struct env *env_data);
static int store_env(char *argvlist[], struct env *env_data);
static int exec_export_cmd(char *argvlist[]);
static int parse_env(char *parse_str, char name[40], char val[40]);
static int exec_unset_cmd(char *argvlist[], struct env *env_data);
static int is_letter(char *str);

int exec_env_cmd(char *argvlist[], struct env *env_data)
{
    if (env_data == NULL) {
        perror("exec_env_cmd data is null\n");
        exit(EXIT_FAILURE);
    }

    if (!strcmp(argvlist[0], "export")) {
        store_env(argvlist, env_data);
        exec_export_cmd(argvlist);
    }

    if (!strcmp(argvlist[0], "set") && argvlist[1] == NULL)
        exec_set_cmd(env_data);

    if (search_ch('=', argvlist))
        store_env(argvlist, env_data);

    if (!strcmp(argvlist[0], "unset")) 
        exec_unset_cmd(argvlist, env_data);

    return TURE;
}

int exec_export_cmd(char *argvlist[])
{
    char name[40], val[40];
    int ret;
    //char *temp = argvlist[1];
    //int str_num = 0;
    ret = parse_env(argvlist[1], name, val);
    if (ret == -1)
        return FAULT;

    setenv(name, val, 1);

    return TURE;
}

/**
 * @brief   将系统环境变量存入env_array[env_count]数组中
 */
int setup_env(struct env *env_data)
{
    if (env_data == NULL) {
        perror("setup_env data is null\n");
        exit(EXIT_FAILURE);
    }
    
    /*链表*/
    int data_len, env_count = 0;
    struct env *env_list = NULL, *env_tmp;

    //char **environ;
    if (env_data == NULL) {
        perror("setup_env is null\n");
        exit(EXIT_FAILURE);
    }

    env_tmp  = env_data;
    while (environ[env_count]) {
        if (!(env_list = (struct env *)calloc(1, sizeof(struct env))))
            printf("error\n");

        memset(env_list, '\0', sizeof(struct env));
        env_tmp->next = env_list;
        env_tmp = env_list;

        data_len = strlen(environ[env_count]);
        strncpy(env_list->env_data, environ[env_count], data_len);
        env_list->env_data[data_len + 1] = '\0';

        env_count++;
    }

    env_list->next = NULL;
    return TURE;
}

/**
 * @brief   实现set命令
 */
int exec_set_cmd(struct env *env_data)
{   
    struct env *env_list;

    if (env_data == NULL) {
        perror("exec_set_cmd data is null\n");
        exit(EXIT_FAILURE);
    }

    env_list = env_data->next;
    while (env_list) {
        printf("%s\n", env_list->env_data);
        env_list = env_list->next;
    }

    return TURE;
}

int free_env(struct env *env_data)
{   
    struct env *env_list, *env_tmp;

    if (env_data == NULL) {
        perror("env_free is null\n");
        exit(EXIT_FAILURE);
    }

    env_list = env_data->next;

    while (env_list) {
        env_tmp = env_list;
        env_list = env_list->next;
        free(env_tmp);
    }
    
    return TURE;
}

/**
 * @brief   存储局部变量， set打印出来可以看到， env看不到
 */
int store_env(char *argvlist[], struct env *env_data)
{   
    int data_len;
    char *cmd_tmp, match_name[1500], find_name[40], val[40];
    struct env *env_list, *env_tmp;

    if (env_data == NULL) {
        perror("store env data is null\n");
        exit(EXIT_FAILURE);
    }

    if (!strcmp(argvlist[0], "export"))
        cmd_tmp = argvlist[1];
    else
        cmd_tmp = argvlist[0];

    parse_env(cmd_tmp, find_name, val);
    if (-1 == is_letter(find_name)) {
        printf("var must be letter\n");
        return FAULT;
    }
    env_list = env_data->next;

    /*match_name exist var*/
    while (env_list) {
        parse_env(env_list->env_data, match_name, NULL);
        if (!strcmp(match_name, find_name)) {
            data_len = strlen(cmd_tmp);
            strncpy(env_list->env_data, cmd_tmp, data_len);
            env_list->env_data[data_len + 1] = '\0';

            if (!strcmp(argvlist[0], "export"))
                setenv(find_name, val , 1);
                
            return TURE;
        }

        env_list = env_list->next;
    }

    env_list = env_data->next;

    while (env_list) {
        if (env_list->next == NULL) {
            env_tmp = (struct env *)calloc(1, sizeof(struct env));
            env_list->next = env_tmp;
            env_tmp->next = NULL;

            data_len = strlen(cmd_tmp);
            strncpy(env_tmp->env_data, cmd_tmp, data_len);
            env_tmp->env_data[data_len + 1] = '\0';

            if (!strcmp(argvlist[0], "export")) {
                //setenv()
                env_tmp->is_common_var = 0;
            }

            break;
        }

        env_list = env_list->next;
    }

    return TURE;
}

/**
 * @brief   找到对应的字符
 */
int search_ch(char ch, char *argvlist[])
{
    char *search_ch = argvlist[0];

    while (*search_ch != '\0') {
        if (*search_ch == ch)
            return IS_MATCHING;

        search_ch++;
    }

    return IS_NOT_MATCHING;
}

int is_env_cmd(char *argvlist[])
{
    if (!strcmp(argvlist[0], "export"))
        return IS_MATCHING;

    if (!strcmp(argvlist[0], "set"))
        return IS_MATCHING;

    if (!strcmp(argvlist[0], "unset"))
        return IS_MATCHING;

    if (search_ch('=', argvlist))
        return IS_MATCHING;

    return IS_NOT_MATCHING;
}

/**
 * @brief   解析环境变量    例如 a = 1；解析处 a 和 1;
 * @param   解析的字符串    变量名  变量的值
 */
int parse_env(char *parse_str, char *name, char *val)
{
    int str_num = 0;
    char *temp = parse_str;

    /*字符串为空，返回*/
     if (!temp)
        return FAULT;

    /*if the argvlist[1] did not have the '=', break*/

    while (*temp != '=' && *temp != '\0') {
        name[str_num++] = *temp;
        temp++;
    }
    name[str_num] = '\0';
    
    temp++;
    str_num = 0;

    if (val != NULL) {
        while (*temp != '\0') {
            val[str_num++] = *temp;
            temp++;
        }
        val[str_num] = '\0';
    }

    return TURE;
}


int exec_unset_cmd(char *argvlist[], struct env *env_data)
{
    char find_name[40], match_name[40];
    struct env *env_list, *env_tmp;
    int ret, is_matching;
    
    if (!env_data) {
        perror("exec_unset_cmd error\n");
        exit(EXIT_FAILURE);
    }
    
    ret = parse_env(argvlist[1], match_name, NULL);
    if (ret == -1)
        return FAULT;
    
    is_matching = -1;
    env_tmp = env_data;
    env_list = env_data->next;
    
    //删除普通变量
    while (env_list) {
        parse_env(env_list->env_data, find_name, NULL);
        if (!strcmp(match_name, find_name)) {
            env_tmp->next = env_list->next;
            free(env_list);
            is_matching = 1;

            break;
        }

        /*指向下一个链表*/
        env_tmp = env_list;
        env_list = env_list->next;
    } 

    if (is_matching == -1) {
        printf("var can not found!\n");
        return FAULT;
    }

    /*判断是否为环境变量，是的话多用一个这个函数*/
    if (env_data->is_common_var == 0) {
        unsetenv(find_name);
    }

    return TURE;
}

int is_letter(char *str)
{
    int count, ret = 1;

    if (!str) {
        perror("str is null\n");
        return FAULT;
    }

    for (count = 0; count < DATA_LENGTH; count++) {
        if (str[count] == '\0')
            break;

        if ((str[count] >= 'A' && str[count] <= 'Z') ||
            (str[count] >= 'a' && str[count] <= 'z')) 
            ret = 1;
        else
        return IS_NOT_MATCHING;
    }

    return ret;
}